#include <iostream>

using namespace std;

// 队列操作 ： 入队 出队 队空/满 扩容 队列大小 队首 队尾
class SeqQueue
{
public:
    SeqQueue(int cap)
        :capacity_(cap)
        ,front_(0)
        ,rear_(0)
        ,size_(0)
    {
        que_ptr_ = new int[capacity_];
    }
    ~SeqQueue()
    {
        delete [] que_ptr_;
    }
    void enQueue(int data);
    int deQueue();
    bool isEmpty();
    bool isFull();
    int size();
    int front();
    int back();
private:
    void expand(size_t new_size);
private:
    int *que_ptr_;
    int front_;
    int rear_;
    int size_;
    int capacity_;
};

bool SeqQueue::isEmpty()
{
    return front_ == rear_;
}

bool SeqQueue::isFull()
{
    return (rear_ + 1) % capacity_ == front_;
}

int SeqQueue::size()
{
    return size_;
}

void SeqQueue::expand(size_t new_cap)
{
    int *new_que_ptr = new int[new_cap];
    int i = 0;
    int j = front_;
    for (; i < size_; i++, j = (j + 1) % capacity_)
    {
        new_que_ptr[i] = que_ptr_[j];
    }
    delete [] que_ptr_;
    que_ptr_ = new_que_ptr;
    front_ = 0;
    rear_ = size_;
    capacity_ = new_cap;
}

void SeqQueue::enQueue(int data)
{
    if (isFull())
    {
        expand(capacity_ * 2);
    }
    que_ptr_[rear_] = data;
    rear_ = (rear_ + 1) % capacity_;
    size_++;
}

int SeqQueue::deQueue()
{
    if (isEmpty())
    {
        throw "queue is empty";
    }
    int data = que_ptr_[front_];
    front_ = (front_ + 1) % capacity_;
    size_--;
    return data;
}

int SeqQueue::front()
{
    if (isEmpty())
    {
        throw "queue is empty";
    }
    return que_ptr_[front_];
}

int SeqQueue::back()
{
    if (isEmpty())
    {
        throw "queue is empty";
    }
    return que_ptr_[rear_ - 1];
}


int main()
{
    int arr[10] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
    SeqQueue que(10);
    for (int val : arr)
    {
        que.enQueue(val);
    }
    que.enQueue(200);
    que.enQueue(300);
    que.enQueue(400);
    que.enQueue(10);
    int length = que.size();
    for (size_t count = 0; count < length; count++)
    {
        cout << que.deQueue() << endl;
    }
    return 0;
}